package pl.edu.agh.thieves.firefly;

import java.text.*;

public class Firefly {

	public void updateBrightness() {
		brightness = enviroment.countValueByCoordinates(coordinates);
	}
  
	public void update(){
		for (int i = 0; i < newCoordinates.getDimension(); ++i)
			if (newCoordinates.getCoordinateByNumber(i) > 1.999)
				newCoordinates.setCoordinateByNumber(i, 1.999);
			else if (newCoordinates.getCoordinateByNumber(i) < 0.000)
				newCoordinates.setCoordinateByNumber(i, 0.000);

		for(int i = 0; i < enviroment.getItemNumber(); ++i)
			coordinates.setCoordinateByNumber(i, newCoordinates.getCoordinateByNumber(i));
		
		updateBrightness();
  }

	public double getBrightness() {
		return brightness;
	}

	public Coordinates getCoordinates() {
		return coordinates;
	}

	public void moveToward(Firefly firefly) {
		double brightnessDifference = firefly.getBrightness() - this.getBrightness();
		Coordinates difference = Coordinates.sub(firefly.getCoordinates(), getCoordinates());
		double distance = difference.getVectorLength();
		double distanceCase = Math.exp(-enviroment.getBeta() * (distance * distance));
		double factor = enviroment.getAlpha() * (brightnessDifference/firefly.getBrightness()) * distanceCase / distance;

		newCoordinates = Coordinates.sum(newCoordinates, Coordinates.multiplyByNumber(factor, difference));
	}

	public void moveRandomly() {

		if(coordinates.equals(newCoordinates) && getBrightness() < 0.01)
			newCoordinates = new Coordinates(enviroment.getItemNumber());
		else{
			Coordinates randomElement = new Coordinates(getCoordinates().getDimension());
			randomElement = Coordinates.multiplyByNumber(enviroment.getGamma(), Coordinates.addNumber(randomElement, -1.0));
			newCoordinates = Coordinates.sum(newCoordinates, randomElement);
		}
	}

	@Override
	public String toString() {
		DecimalFormat f = new DecimalFormat("0.00");
		return "Firefly <" + f.format(getBrightness()) + "> " + getCoordinates().toString();
	}


	public Firefly(Coordinates coordinates, Enviroment enviroment) {
		this.coordinates = coordinates;
		this.enviroment = enviroment;
		this.newCoordinates = new Coordinates(coordinates.getDimension());
		for(int i = 0; i < enviroment.getItemNumber(); ++i)
			newCoordinates.setCoordinateByNumber(i, coordinates.getCoordinateByNumber(i));
		
		updateBrightness();
	}

 
	public Firefly(Enviroment enviroment) {
		this(new Coordinates(enviroment.getItemNumber()), enviroment);
	}

	private double brightness = 0;
	private Coordinates coordinates = null;
	private Coordinates newCoordinates = null;
	private Enviroment enviroment = null;

}
